package tolietdemo.sync;

//租客类，客户类
class Customer implements Runnable {

    private Toliet toliet;

    public Customer(Toliet toliet) {
        this.toliet = toliet;
    }

    @Override
    public void run() {
        //开始来描述这个故事....
        //怎么写呢？
        try {
            //注意：一定要给卫生间先上锁，保证在一个同步代码块中。。。
            synchronized (toliet) {
                //判断一下是否是小张的线程
                if ("小张".equals(Thread.currentThread().getName())) {
                    //先嘘嘘...
                    toliet.xuxu();
                    //嘘嘘完了之后，释放卫生间的锁。。。。
                    toliet.notifyAll(); //唤醒小李进入卫生间解小便...
                    toliet.wait(); //释放锁。//小张进入到等待队列中..

                    toliet.brushTeeth();
                    toliet.notifyAll();//唤醒小李进入卫生间刷牙...

                } else {
                    toliet.xuxu(); //小李可以嘘嘘了。。。。
                    toliet.notifyAll();//唤醒小张去刷牙...
                    toliet.wait();
                    toliet.brushTeeth();
                    //故事就结束了。
                }
            }

        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
}


//卫生间类
class Toliet {
    //定义两个方法。
    //解小便的方法...
    public synchronized void xuxu() {
        try {
            System.out.println(Thread.currentThread().getName() + "正在卫生间嘘嘘...");
            Thread.sleep(50);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    //刷牙
    public synchronized void brushTeeth() {
        try {
            System.out.println(Thread.currentThread().getName() + "正在卫生间刷牙...");
            Thread.sleep(50);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
}

public class TolietDemo {

    public static void main(String[] args) {

        Toliet toliet = new Toliet();

        Customer zhang = new Customer(toliet);
        Customer li = new Customer(toliet);  //这里一定是同一个卫生间对象。
        Thread zhangThread = new Thread(zhang, "小张");
        Thread liThread = new Thread(li, "小李");

        //小张先起床，意味：小张线程先执行。
        //如何保证小张线程先执行呢。
        zhangThread.start();
        //采用卑鄙无耻的手段。
        try {
            Thread.sleep(50);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        liThread.start();
    }
}